home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************\
- *
- * Apple Macintosh Developer Technical Support
- *
- * Picture Document routines
- *
- * Program: ColorReset
- * File: PictDocument.c
- *
- * by: Forrest Tanaka
- *
- * Copyright © 1988-1992 Apple Computer, Inc.
- * All rights reserved.
- *
- * This source file is the most important part of this program because it shows
- * all the code needed to maintain Picture Documents. A Picture Document is a
- * window which displays an off-screen image and lets you paint into it, and
- * these two activities show how to use graphics environments to draw off screen
- * and copy the off-screen image to the window on the screen.
- *
- \******************************************************************************/
-
-
- /******************************************************************************\
- * Header Files
- \******************************************************************************/
-
- /* System header files needed by MPW C */
- #ifndef THINK_C
- #include <Errors.h>
- #include <Menus.h>
- #include <Resources.h>
- #include <Windows.h>
- #endif
-
- #include <GestaltEqu.h>
- #include <Palettes.h>
- #include <Picker.h>
- #include <QDOffscreen.h>
-
- /* Header files specific to this program */
- #include "PictDocument.h"
- #include "EmergMem.h"
- #include "Exceptions.h"
- #include "ColorReset.h"
- #include "MenuHandler.h"
- #include "WindowPositioner.h"
-
-
- /******************************************************************************\
- * Private Constants
- \******************************************************************************/
-
- /* Picture Document window constants */
- #define rPictDocWindID 128 /* Resource ID of Picture Document WIND resource */
- #define rScrollBarID 128 /* Resource ID of scroll bar CNTL resource */
- #define kDocWKind 128 /* windowKind field of Picture Document windows */
- #define kMinWindowSize 64 /* Minimum size of the window in pixels */
-
- /* PICT file constants */
- #define kPictFileHeaderSize 512 /* Number of bytes in PICT file header */
- #define kFileCreator 'CLIM' /* Creator code for this application */
- #define kFileType 'PICT' /* File type for this app’s documents */
-
- /* Off-screen Constants */
- #define kMaxRowBytes 0x3FFE /* Maximum number of bytes in a row of pixels */
- #define kDefaultRes 0x00480000 /* Default resolution is 72 DPI; Fixed type */
- #define kITabRes 4 /* Inverse-table resolution */
-
- /* Miscellaneous constants */
- #define kPaintRadius 8 /* Radius of a drop of paint in pixels */
-
-
- /******************************************************************************\
- * Private Types
- \******************************************************************************/
-
- /* Picture Document information */
- typedef struct
- {
- GWorldPtr image; /* Pointer to image in off-screen GWorld */
- Rect windowRect; /* Rectangle of window except for scroll bars */
- Rect destRect; /* Rectangle of image in window */
- RGBColor foreground; /* Color of foreground */
- RGBColor background; /* Color of background */
- ControlHandle vScrollBar; /* Horizontal scroll bar */
- ControlHandle hScrollBar; /* Vertical scroll bar */
- FSSpec file; /* File spec of Picture Document’s PICT file */
- short fileRef; /* File ref # of Picture Document’s PICT file */
- Boolean dithering; /* True if image should be dithered */
- } PictDocInfoRec, *PictDocInfoPtr, **PictDocInfoHnd;
-
- /* Basic picture information */
- typedef struct
- {
- CTabHandle colors; /* Handle to color table of deepest pixel map */
- short depth; /* Max depth for all pixmaps (in the picture) */
- Rect frame; /* Picture frame rect (contains entire picture) */
- } PictureInfoRec;
-
-
- /******************************************************************************\
- * Prototypes of Private Functions
- \******************************************************************************/
-
- static OSErr CreatePictDoc(
- Rect *pictureRect,
- short pictureDepth,
- CTabHandle pictureClut,
- WindowPtr *retDoc);
-
- pascal void ScrollActionProc(
- ControlHandle control,
- short part);
-
- static void ScrollPictDoc(
- WindowPtr docWindow,
- short hScrollDelta,
- short vScrollDelta);
-
- void ResizePictDoc(
- WindowPtr docWindow);
-
- OSErr CreateOffScreen(
- Rect *bounds,
- short depth,
- CTabHandle colors,
- CGrafPtr *retPort,
- GDHandle *retGDevice);
-
- OSErr SetUpPixMap(
- short depth,
- Rect *bounds,
- CTabHandle colors,
- short bytesPerRow,
- PixMapHandle aPixMap);
-
- OSErr CreateGDevice(
- PixMapHandle basePixMap,
- GDHandle *retGDevice);
-
- void DisposeOffScreen(
- CGrafPtr doomedPort,
- GDHandle doomedGDevice);
-
- OSErr GetPictureInfo(
- short pictFileRef,
- PictureInfoRec *retPictInfo);
-
- pascal void InfoBits(
- BitMapPtr srcBits,
- Rect *srcRect,
- Rect *dstRect,
- short mode,
- RgnHandle maskRgn);
-
- OSErr DrawFilePicture(
- short pictFileRef,
- Rect *destRect);
-
- pascal void FileGetPic(
- Ptr dataPtr,
- short byteCount);
-
- OSErr OpenFilePicture(
- short pictFileRef,
- Rect *sourceRect);
-
- OSErr CloseFilePicture(void);
-
- pascal void FilePutPic(
- Ptr dataPtr,
- short byteCount);
-
-
- /******************************************************************************\
- * Global Variables
- \******************************************************************************/
-
- PictureInfoRec gPictureInfo; /* Information about a PICT file */
- PicHandle gSpoolPicture; /* Temporary picture used to spool from PICT file */
- QDProcsPtr gSavedProcs; /* Saves existing QDProcs; used when spooling out */
- CQDProcs gCustomProcs; /* Customized bottlenecks to spool to PICT file */
- short gPictFileRef; /* File reference number of a PICT file */
- short gPictureSize; /* Size of picture in bytes */
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * FindPictDoc: Find the Picture Document window for a specific file
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * Each Picture Document window in the window list is examined to see whether it
- * has a corresponding disk file. The fileRef field of the Picture Document
- * information record is non-zero if the Picture Document has a disk file
- * associated with it. If there is a disk file, then EqualFSSpec is called to
- * see if the FSSpec that I saved in the document’s info record is the same as
- * the one passed in fileSpec. If they are, then a pointer to the window is
- * returned. Otherwise, the loop goes to the next Picture Document window, if
- * there is one.
- *
- * See ColorReset.h for a definition of EqualFSSpec.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- WindowPtr FindPictDoc(
- FSSpecPtr fileSpec) /* Specification of file to search for */
- {
- WindowPtr pictDocWindow; /* Pointer to Picture Document being tested */
- PictDocInfoHnd pictDocInfo; /* Handle to Picture Document info rec */
- Boolean foundDoc; /* True if found Pict Doc w/ same FSSpec */
-
- /* Get a pointer to the first Picture Document window in the window list */
- pictDocWindow = NextPictDocWindow( nil );
-
- /* Keep searching until found or at end of list */
- foundDoc = false;
- while (pictDocWindow != nil && !foundDoc)
- {
- /* Only have to check FSSpecs if document has a corresponding file */
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( pictDocWindow );
- if ((**pictDocInfo).fileRef != 0)
- {
- /* See if the Picture Document’s file is same as fileSpec */
- HLock( (Handle)pictDocInfo );
- foundDoc = EqualFSSpec( fileSpec, &(**pictDocInfo).file );
- HUnlock( (Handle)pictDocInfo );
-
- /* If FSSpecs aren’t the same, then go to next Picture Document */
- if (!foundDoc)
- pictDocWindow = NextPictDocWindow( pictDocWindow );
- }
- }
-
- return pictDocWindow;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * NextPictDocWindow: Return a pointer to the next Picture Document window
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * NextPictDocWindow goes through every window in the window list that’s behind
- * the window specified by aWindow until either a Picture Document window is
- * found or until the end of the window list is reached. If aWindow is nil, then
- * the search starts with the front window.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- WindowPtr NextPictDocWindow(
- WindowPtr aWindow) /* Window to start search from, or nil if front */
- {
- /* Start search from next window, or front window if aWindow is nil */
- if (aWindow == nil)
- aWindow = FrontWindow();
- else
- aWindow = (WindowPtr)((WindowPeek)aWindow)->nextWindow;
-
- /* Search until Picture Document wind found or end of wind list reached */
- while (aWindow != nil && !IsPictDocWindow( aWindow ))
- aWindow = (WindowPtr)((WindowPeek)aWindow)->nextWindow;
-
- return aWindow;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * IsPictDocWindow: Is a window a Picture Document window?
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * When I create a window, I store a code for that kind of window in the
- * windowKind field. IsPictDocWindow checks the windowKind field of the given
- * window against the constant kDocWKind. If they’re equal, then aWindow
- * must be a Picture Document window.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- Boolean IsPictDocWindow (
- WindowPtr aWindow) /* Pointer to the window being tested */
- {
- return ((WindowPeek)aWindow)->windowKind == kDocWKind;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * DrawPictDoc: Draw the contents of a Picture Document
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * The image for Picture Documents is stored in an off-screen GrafPort, and its
- * GrafPtr is stored in the information record. This GrafPtr is retrieved, and
- * it’s used to CopyBits the GrafPort to the window. It’s possible that not all
- * of the image can be copied to the window. For example, part of the window
- * might be covered by another window. In this case, the visRgn of the window
- * takes care of clipping out the undesireable parts of the original image. The
- * other case in which part of the image shouldn’t be drawn is if part of the
- * image is scrolled out of the window. The visRgn of the window takes care of
- * part of this, but we still have to make sure that the image doesn’t draw
- * itself over the scroll bar areas of the window in case the scroll bars are
- * hidden, which they are if the window is inactive. To take care of this, the
- * destination rectangle which is the rectangle that the off-screen image is
- * copied to, is first intersected with the window rectangle, which is the
- * rectangle of the window except for the scroll bars. This is used as the
- * destination rectangle to CopyBits. Then this rectangle is offset by the top-
- * left corner of the original destination rectangle, and this is used as the
- * source rectangle to CopyBits. The off-screen image is then copied to the
- * window.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- void DrawPictDoc(
- WindowPtr docWindow) /* Ptr to Picture Document window being drawn */
- {
- PictDocInfoHnd pictDocInfo; /* Handle to Picture Document information rec */
- GWorldPtr image; /* Pointer to the off-screen image */
- Rect destRect; /* Rectangle to copy image into */
- Rect sourceRect; /* Rectangle to copy image from */
- Rect windowRect; /* Rect of the window except for scroll bars */
- short mode; /* Drawing mode to use */
-
- /* Get a pointer to the off-screen image and the window rectangle */
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
- image = (**pictDocInfo).image;
- windowRect = (**pictDocInfo).windowRect;
-
- /* Calculate the rectangle to copy the image to */
- destRect = (**pictDocInfo).destRect;
- (void)SectRect( &destRect, &windowRect, &destRect );
-
- /* Calculate the rectangle to copy the image from */
- sourceRect = destRect;
- OffsetRect( &sourceRect, -(**pictDocInfo).destRect.left,
- -(**pictDocInfo).destRect.top );
-
- /* Specify the drawing mode to use */
- mode = srcCopy;
- if ((**pictDocInfo).dithering)
- mode |= ditherCopy;
-
- /* Draw the off-screen image to the screen */
- EraseRect( &docWindow->portRect );
- CopyBits( &((GrafPtr)image)->portBits, &docWindow->portBits,
- &sourceRect, &destRect,
- mode, nil );
-
- /* Draw the grow box */
- DrawGrowIcon( docWindow );
-
- /* Draw the scroll bars */
- DrawControls( docWindow );
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * ClickPictDoc: Handle a mouse click in a Picture Document window
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * The first really important call in this routine is FindControl, which is the
- * toolbox call which tells you which control and which part of the control the
- * mouse was clicked in. If it returns zero, then the mouse was clicked outside
- * of any control, and so we let the user paint into the document.
- *
- * Painting into the document is done within a loop which iterates as long as the
- * mouse button is held down. While this is the case, the current mouse position
- * is retrieved with a call to GetMouse. If the mouse position changed from the
- * previous iteration’s mouse position, then the mouse position is offset to take
- * into account the currently-scrolled position, and then the current port is set
- * to the document’s off-screen GrafPort. Then, PaintOval is called which draws
- * a drop of paint into the off-screen GrafPort.
- *
- * The off-screen image then has to be copied to the window so that the user can
- * see the new drop of paint. This is done by first seeing if the drop of paint
- * can actually be seen in the window in the currently-scrolled position. If it
- * can, then the rectangle of the drop of paint is offset to take into account
- * the currently-scrolled position. Then the current port is set to the document
- * window, and CopyBits is called to copy the new drop of paint to the document
- * window.
- *
- * Finally, the mouse position is remembered and the loop iterates again if the
- * mouse button is still held down.
- *
- * If FindControl indicates that the mouse click was in the thumb of a scroll
- * bar, TrackControl is called which lets the user move the thumb around until
- * the user releases the mouse button. Then, the difference between the old and
- * new scroll bar position is calculated which indicates the number of pixels
- * that the document must be scrolled. ScrollPictDoc, defined below, is then
- * called to scroll the document’s image, update the scrolled-in part of the
- * image, and update the document information record to reflect the new scrolled
- * position.
- *
- * If FindControl indicates that the mouse click was in the up arrow, down arrow,
- * page up, or page down areas of either scroll bar, then TrackControl is called
- * to scroll the document appropriately. The ScrollActionProc routine, defined
- * below, handles the logistics of scrolling in this case.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- void ClickPictDoc(
- WindowPtr docWindow, /* Picture Document window that was clicked */
- EventRecord *clickEvent) /* Mouse click event */
- {
- PictDocInfoHnd pictDocInfo; /* Handle to Picture Document info rec */
- GWorldPtr image; /* Pointer to the off-screen image */
- GDHandle savedDevice; /* Saves default GDevice */
- Rect paintRect; /* Rectangle to draw paint into */
- Rect windowPaintRect; /* Rectangle to draw paint into */
- Rect windowRect; /* Window rect except for scroll bars */
- Rect destRect; /* Rectangle of image in window */
- Point newPosition; /* New pos of mouse click; local coords */
- Point oldPosition; /* Old pos of mouse click; local coords */
- ControlHandle scrollBar; /* Handle to the clicked scroll bar */
- short partNumber; /* Part # of clicked part of control */
- short scrollDelta; /* Number of pixels to scroll */
-
- savedDevice = GetGDevice();
-
- /* Get information about the Picture Document */
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
- image = (**pictDocInfo).image;
- windowRect = (**pictDocInfo).windowRect;
- destRect = (**pictDocInfo).destRect;
-
- /* Get the mouse click position */
- SetPort( docWindow );
- newPosition = clickEvent->where;
- GlobalToLocal( /*◊*/&newPosition );
-
- /* Find whether the mouse was in a control */
- partNumber = FindControl( newPosition, docWindow, /*<*/&scrollBar );
- switch (partNumber)
- {
- case 0:
- /* Clicked outside of any control; see if it was in the image */
- if (PtInRect( newPosition, &windowRect ))
- {
- /* Click in image; paint while mouse button is held down */
- oldPosition.v = oldPosition.h = -32767;
- while (StillDown())
- {
- /* Only do something if the mouse moved */
- if (!EqualPt( newPosition, oldPosition ))
- {
- /* Need to offset paint brush for scrolled position */
- SubPt( topLeft( destRect ), /*◊*/&newPosition );
- SetRect( /*<*/&paintRect, newPosition.h - kPaintRadius,
- newPosition.v - kPaintRadius,
- newPosition.h + kPaintRadius,
- newPosition.v + kPaintRadius );
-
- /* Drop some paint into the off-screen image */
- SetGWorld( image, nil );
- PaintOval( &paintRect );
-
- /* Offset brush back to window position */
- AddPt( topLeft( destRect ), /*◊*/&newPosition );
-
- /* Calc rect in window for to brush rect in image */
- windowPaintRect = paintRect;
- OffsetRect( &windowPaintRect, destRect.left,
- destRect.top );
-
- /* Only copy if some part of brush within image */
- if (SectRect( &windowPaintRect, &windowRect,
- &windowPaintRect ))
- {
- /* Make clipped paint rect in off-screen image */
- paintRect = windowPaintRect;
- OffsetRect( &paintRect, -destRect.left,
- -destRect.top );
-
- /* Copy painted off-screen image to the screen */
- SetGWorld( (CGrafPtr)docWindow, nil );
- CopyBits( &((GrafPtr)image)->portBits, &docWindow->portBits,
- &paintRect, &windowPaintRect,
- srcCopy, nil );
- }
-
- /* Remember the new mouse position */
- oldPosition = newPosition;
- }
-
- /* Get the new position of the mouse */
- SetPort( docWindow );
- GetMouse( /*<*/&newPosition );
- }
- }
- break;
- case inThumb:
- /* Mouse in thumb of scroll bar; get existing control value */
- scrollDelta = GetCtlValue( scrollBar );
-
- /* Track mouse in thumb until mouse button is released */
- partNumber = TrackControl( scrollBar, newPosition, nil );
- if (partNumber != 0)
- {
- /* Find diff between old and new scroll bar values */
- scrollDelta -= GetCtlValue( scrollBar );
- if (scrollDelta != 0)
- {
- if (scrollBar == (**pictDocInfo).vScrollBar)
- ScrollPictDoc( docWindow, 0, scrollDelta );
- else
- ScrollPictDoc( docWindow, scrollDelta, 0 );
- }
- }
- break;
- case inUpButton:
- case inDownButton:
- case inPageUp:
- case inPageDown:
- (void)TrackControl( scrollBar, newPosition, (ProcPtr)ScrollActionProc );
- break;
- default:
- break;
- }
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * ScrollActionProc: Handle a click in a scroll bar (except for thumb)
- *
- * PARAMETERS:
- * ControlHandle control: Control that received the mouse click
- * short part: Part number of the clicked control part
- *
- * DEFINITION:
- * ScrollActionProc is called by the Control Manager when TrackControl is called
- * in the ClickPictDoc function above. It handles scrolling when the user clicks
- * in the scroll arrows or page areas of the scroll bar. The document is
- * scrolled by the appropriate amount.
- *
- * DESCRIPTION:
- * ScrollActionProc first checks to see which part of the scroll bar was clicked.
- * If it was in either of the arrows, then the desired scroll amount is one
- * pixel. If it was in either of the paging areas, then the desired scroll
- * amount is 32 pixels. The current value of the clicked scroll bar is then
- * adjusted by the desired scroll amount, and the result is compared against the
- * limits of the scroll bar’s values. If the new value is beyond either limit,
- * then it’s pinned back into the limits. Then the real amount to scroll is
- * calculated simply by subtracting the new scroll value from the old scroll
- * value, and ScrollPictDoc (defined below) is called to scroll the Picture
- * Document window.
- *
- * RETURN VALUES:
- * None
- \******************************************************************************/
-
- static pascal void ScrollActionProc(
- ControlHandle control, /* Handle to clicked control */
- short part) /* Part number of clicked control part */
- {
- PictDocInfoHnd pictDocInfo; /* Handle to Picture Document info rec */
- WindowPtr docWindow; /* Clicked Picture Document window */
- Rect windowRect; /* Window rect except for scroll bars */
- Rect destRect; /* Rectangle of image in window */
- short scrollDelta; /* Number of pixels to scroll by */
- short oldValue; /* Value of scroll bar before scrolling */
- short newValue; /* Value of scroll bar after scrolling */
- short maxValue; /* Maximum value of the scroll bar */
-
- /* Get information about the Picture Document */
- docWindow = (**control).contrlOwner;
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
- windowRect = (**pictDocInfo).windowRect;
- destRect = (**pictDocInfo).destRect;
-
- /* Only process if the part # isn’t zero */
- if (part != 0)
- {
- /* Decide scroll amount based on part of control that was clicked */
- switch (part)
- {
- case inUpButton:
- scrollDelta = 1;
- break;
- case inDownButton:
- scrollDelta = -1;
- break;
- case inPageUp:
- scrollDelta = 32;
- break;
- case inPageDown:
- scrollDelta = -32;
- break;
- default:
- scrollDelta = 0;
- break;
- }
-
- /* Only do something if we’re actually scrolling */
- if (scrollDelta != 0)
- {
- /* Get the current scroll bar state */
- maxValue = GetCtlMax( control );
- oldValue = GetCtlValue( control );
-
- /* Calculate the new scroll bar value pinned to the limits */
- newValue = oldValue - scrollDelta;
- if (newValue < 0)
- newValue = 0;
- else if (newValue > maxValue)
- newValue = maxValue;
-
- /* Only scroll if the old and new values are different */
- if (oldValue != newValue)
- {
- /* Set the new value of the scroll bar */
- SetCtlValue( control, newValue );
-
- /* Scroll by difference between old and new scroll bar values */
- scrollDelta = oldValue - newValue;
- if (control == (**pictDocInfo).vScrollBar)
- ScrollPictDoc( docWindow, 0, scrollDelta );
- else
- ScrollPictDoc( docWindow, scrollDelta, 0 );
- }
- }
- }
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * ScrollPictDoc: Scroll a Picture Document window’s image
- *
- * PARAMETERS:
- * WindowPtr docWindow: Pointer to Picture Document window to scroll
- * short vScrollDelta: Number of pixels to scroll vertically
- * short hScrollDelta: Number of pixels to scroll horizontally
- *
- * DEFINITION:
- * ScrollPictDoc scrolls the picture document window specified by the docWindow
- * parameter by vScrollDelta pixels vertically and hScrollDelta pixels
- * horizontally. The part of the window that’s scrolled in is updated, so no
- * updating is needed outside of ScrollPictDoc.
- *
- * DESCRIPTION:
- * ScrollRect is called to scroll the Picture Document’s image by the specified
- * amount. The scrolled-in part is then redrawn with a call to CopyBits. The
- * destRect field of the Picture Document information record keeps track of the
- * scrolled position of the image, so it’s updated to reflect the new scrolled
- * position.
- *
- * RETURN VALUES:
- * None
- \******************************************************************************/
-
- static void ScrollPictDoc(
- WindowPtr docWindow, /* Pointer to document window to scroll */
- short hScrollDelta, /* Number of pixels to scroll horizontally */
- short vScrollDelta) /* Number of pixels to scroll vertically */
- {
- PictDocInfoHnd pictDocInfo; /* Handle to Picture Document info rec */
- RgnHandle updateRegion; /* Region covering scrolled-in area */
- Rect windowRect; /* Rect of window except for scroll bars */
- Rect destRect; /* New destination rectangle */
- GWorldPtr image; /* Off-screen document image */
-
- /* Get the window rectangle and destination rectangle */
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
- windowRect = (**pictDocInfo).windowRect;
- destRect = (**pictDocInfo).destRect;
- image = (**pictDocInfo).image;
-
- /* Scroll the image by the specified amount */
- updateRegion = NewRgn();
- ScrollRect( &windowRect, hScrollDelta, vScrollDelta, updateRegion );
-
- /* Update the destination rectangle to the new scrolled position */
- OffsetRect( &destRect, hScrollDelta, vScrollDelta );
- (**pictDocInfo).destRect = destRect;
-
- /* Update the scrolled-in part of the window */
- CopyBits( &((GrafPtr)image)->portBits, &docWindow->portBits,
- &image->portRect, &destRect,
- srcCopy, updateRegion );
-
- /* Get rid of the update region */
- DisposeRgn( updateRegion );
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * GrowPictDoc: Let the user change the size of a Picture Document window
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * GrowWindow is called with a boundary rectangle that specifies that the window
- * has a minimum size of kMinWindowSize (defined at the top of this source file)
- * and a maximum size that’s the size of the image. After the user releases the
- * mouse button, SizeWindow is called to change the size of the window, and
- * ResizePictDoc (defined below) is called to update the Picture Document to the
- * new size.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- void GrowPictDoc(
- WindowPtr docWindow, /* Picture Document window that’s to be grown */
- EventRecord *clickEvent) /* Mouse down event */
- {
- PictDocInfoHnd pictDocInfo; /* Handle to Picture Document info rec */
- Rect growBounds; /* Window can be dragged over this rectangle */
- Point newSize; /* New size of the new window */
-
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
-
- growBounds = (**pictDocInfo).image->portRect;
- growBounds.left = growBounds.top = kMinWindowSize;
- growBounds.right += kScrollBarWidth;
- growBounds.bottom += kScrollBarWidth;
-
- /* Let the user resize the window to any size */
- *((long *)&newSize) = GrowWindow( docWindow, clickEvent->where,
- &growBounds );
-
- /* If the user actually changed the size of the window, resize the window */
- if (*((long *)&newSize) != 0)
- {
- SizeWindow( docWindow, newSize.h, newSize.v, true );
- ResizePictDoc( docWindow );
- }
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * ResizePictDoc: Update a picture document window to a new size
- *
- * PARAMETERS:
- * WindowPtr docWindow: Picture document window that was resized
- *
- * DEFINITION:
- * ResizePictDoc updates the Picture Document window specified by the docWindow
- * to a new size. This routine is called right after the size of docWindow has
- * been changed. The act of updating the Picture Document window involves moving
- * the scroll bars to the edge of the window and scrolling the document image.
- * The image has to be scrolled when the window is grown in case the bottom or
- * right edge of the window goes below or to the right of the image, in which
- * case the bottom or right edges of the image has to “chase” the bottom or right
- * edges of the window, and that means scrolling.
- *
- * DESCRIPTION:
- * The first major thing that’s done is a new destination rectangle is calculated
- * in case the document has to be scrolled as described in the definition. There
- * are three conditions that have to be met before scrolling can happen:
- * 1) The upper-left corner of destRect must not be (0,0), meaning that the
- * document’s image is scrolled from its original position.
- * 2) The window has become bigger.
- * 3) The window’s rectangle has moved below or to the right of the image in
- * the window.
- * If all three of these conditions are met for either the horizontal or
- * vertical cases, a new destRect is calculated. If this new destRect is
- * different from the old destRect, ScrollPictDoc (defined above) is called to
- * scroll the image to the new position.
- *
- * After this, the windowRect field of the Picture Document information record
- * is updated to the new size of the window. Then, the maximum values of the
- * scroll bars are set to the number of pixels in the horizontal or vertical
- * direction that can’t be seen. And then, the old position of the scroll icon
- * is invalidated so that it’ll be erased with the document’s image the next time
- * the window is updated.
- *
- * Both of the scroll bars are then moved along the bottom and right edges of the
- * window, and the new position of the grow icon is invalidated so that it’s
- * redrawn in case the window was made smaller. Finally, the rectangles of the
- * scroll bars are validated so that they won’t be redrawn in the next update
- * event.
- *
- * RETURN VALUES:
- * None
- \******************************************************************************/
-
- static void ResizePictDoc(
- WindowPtr docWindow) /* Picture document window that was resized */
- {
- PictDocInfoHnd pictDocInfo; /* Handle to Picture Document information rec */
- ControlHandle vScrollBar; /* Vertical scroll bar */
- ControlHandle hScrollBar; /* Horizontal scroll bar */
- Rect windowRect; /* Covers part of window that contains image */
- Rect newWindowRect; /* Covers all of window except scroll bars */
- Rect scrollRect; /* Rectangle of scroll bar */
- Rect destRect; /* Rectangle of to draw image into */
- Rect newDestRect; /* Rectangle of to draw image into */
- CGrafPtr image; /* Off-screen document image */
- short remaining; /* # rows, columns of pixels not visible */
-
- SetPort( docWindow );
-
- /* Get the Picture Document’s information */
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
- vScrollBar = (**pictDocInfo).vScrollBar;
- hScrollBar = (**pictDocInfo).hScrollBar;
- image = (**pictDocInfo).image;
- destRect = (**pictDocInfo).destRect;
- windowRect = (**pictDocInfo).windowRect;
-
- /* Find the new window document area */
- newWindowRect = docWindow->portRect;
- newWindowRect.right -= kScrollBarWidth - 1;
- newWindowRect.bottom -= kScrollBarWidth - 1;
-
- /* Find new destRect in case window growing causes scrolling */
- newDestRect = destRect;
- if (newDestRect.left != 0 &&
- (newWindowRect.right - newWindowRect.left) >
- (windowRect.right - windowRect.left) &&
- newWindowRect.right > newDestRect.right)
- OffsetRect( /*◊*/&newDestRect, (newWindowRect.right - windowRect.right)
- - (newDestRect.right - windowRect.right), 0 );
- if (newDestRect.top != 0 &&
- (newWindowRect.bottom - newWindowRect.top) >
- (windowRect.bottom - windowRect.top) &&
- newWindowRect.bottom > newDestRect.bottom)
- OffsetRect( /*◊*/&newDestRect, 0, (newWindowRect.bottom -
- windowRect.bottom) - (newDestRect.bottom - windowRect.bottom) );
-
- /* If the new scrolled position has changed, update the window’s image */
- if (!EqualRect( &newDestRect, &destRect))
- ScrollPictDoc( docWindow, newDestRect.left - destRect.left,
- newDestRect.top - destRect.top );
-
- /* Set up the rectangles for scroll bar calculations */
- (**pictDocInfo).windowRect = newWindowRect;
-
- /* Calc # rows of image not visible; set as max value of scroll bar */
- remaining = image->portRect.bottom - newWindowRect.bottom;
- if (remaining < 0)
- remaining = 0;
- SetCtlMax( vScrollBar, remaining );
-
- /* Calc # cols of image not visible; set as max value of scroll bar */
- remaining = image->portRect.right - newWindowRect.right;
- if (remaining < 0)
- remaining = 0;
- SetCtlMax( hScrollBar, remaining );
-
- /* Invalidate the old position of the grow icon */
- SetRect( &scrollRect, (**hScrollBar).contrlRect.right,
- (**vScrollBar).contrlRect.bottom,
- (**vScrollBar).contrlRect.right,
- (**hScrollBar).contrlRect.bottom );
- InvalRect( &scrollRect );
-
- /* Move the scroll bars along the edges of the window */
- HideControl( vScrollBar );
- HideControl( hScrollBar );
- MoveControl( vScrollBar, newWindowRect.right, newWindowRect.top - 1 );
- MoveControl( hScrollBar, newWindowRect.left - 1, newWindowRect.bottom );
- SizeControl( vScrollBar, kScrollBarWidth, newWindowRect.bottom -
- newWindowRect.top + 2 );
- SizeControl( hScrollBar, newWindowRect.right - newWindowRect.left + 2,
- kScrollBarWidth );
- ShowControl( vScrollBar );
- ShowControl( hScrollBar );
-
- /* Invalidate the new position of the grow icon */
- SetRect( &scrollRect, (**hScrollBar).contrlRect.right,
- (**vScrollBar).contrlRect.bottom,
- (**vScrollBar).contrlRect.right,
- (**hScrollBar).contrlRect.bottom );
- InvalRect( &scrollRect );
-
- /* Validate the new scroll bar areas */
- scrollRect = (**vScrollBar).contrlRect;
- ValidRect( &scrollRect );
- scrollRect = (**hScrollBar).contrlRect;
- ValidRect( &scrollRect );
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * ActivatePictDoc: Activate or deactivate a Picture Document window
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * If the Picture Document window is becoming active, the scroll bars are shown.
- * If it’s becoming inactive, the scroll bars are hidden. Because hiding
- * controls causes the control rectangle to be invalidated, ActivatePictDoc
- * validates them again to avoid a very slight flicker in the lines that delimit
- * the scroll bar areas.
- *
- * DrawGrowIcon is called to show or hide the grow icon. The Window Manager
- * automatically decides whether to show or hide the grow icon.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- void ActivatePictDoc(
- WindowPtr docWindow, /* Pointer to Doc window being updated */
- Boolean becomingActive) /* True if Doc wind is becoming active */
- {
- PictDocInfoHnd pictDocInfo; /* Handle to Picture Document information rec */
- ControlHandle vScrollBar; /* Vertical scroll bar */
- ControlHandle hScrollBar; /* Horizontal scroll bar */
- Rect scrollRect; /* Rectangle of the scroll bars */
-
- /* Get the scroll bars of the window */
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
- vScrollBar = (**pictDocInfo).vScrollBar;
- hScrollBar = (**pictDocInfo).hScrollBar;
-
- /* Show scroll bars if becoming active; hide if becoming inactive */
- if (becomingActive)
- {
- ShowControl( vScrollBar );
- ShowControl( hScrollBar );
- }
- else
- {
- HideControl( vScrollBar );
- HideControl( hScrollBar );
-
- /* To avoid a slight flicker, validate the scroll bar rectangles */
- SetPort( docWindow );
- scrollRect = (**vScrollBar).contrlRect;
- ValidRect( &scrollRect );
- scrollRect = (**hScrollBar).contrlRect;
- ValidRect( &scrollRect );
- }
-
- /* Show or hide the grow icon */
- DrawGrowIcon( docWindow );
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * FixPictDocMenus: Dim, undim, check, or uncheck menus for Picture Documents
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * The Close and Save As… items in the File menu are enabled when a Picture
- * Document window is active, as is the Choose Color… item in the Colors menu.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- void FixPictDocMenus(
- WindowPtr docWindow) /* Pointer to active Picture Document window */
- {
- #pragma unused(docWindow)
- MenuHandle aMenu; /* Handle to the menus being udpated */
-
- /* Set items in the File menu */
- aMenu = GetMHandle( mFile );
- EnableItem( aMenu, iClose );
- EnableItem( aMenu, iSaveAs );
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * DoOpenPictDoc: Open a new Picture Document
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * The usual Standard File dialog is used to get the name and location of the
- * PICT file to open. Then FindPictDoc (defined earlier in this file) is called
- * to determine whether the chosen PICT file is already open within this
- * application. If it is, then that PICT file’s window is just selected and
- * DoOpenPictDoc returns with a pointer to that window.
- *
- * If the file isn’t open, then it’s opened here with HOpenDF. This routine is
- * used because it works even on systems that don’t have the FSSpec-based File
- * Manager calls. GetPictureRect (defined later in this file) is called to get
- * the picFrame from the picture in the chosen PICT file. Once this is done,
- * CreatePictDoc is called to create a blank Picture Document window that’s ready
- * to read the image into.
- *
- * The current port is set to the off-screen GrafPort that CreatePictDoc created,
- * and then DrawFilePicture (defined later in this file) is called to spool the
- * PICT file into the current port.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- WindowPtr DoOpenPictDoc()
- {
- WindowPtr pictDocWindow; /* Pointer to new Picture Doc window */
- PictDocInfoHnd pictDocInfo; /* Handle to Picture Document info rec */
- PictureInfoRec pictureInfo; /* PixMap information from PICT file */
- Rect pictureRect; /* Rectangle of picture in PICT file */
- CGrafPtr newImage; /* New off-screen image */
- RGBColor color; /* Use to set default fore/back colors */
- CGrafPtr savedPort; /* Ptr to current port for restoring */
- GDHandle savedDevice; /* Current GDevice for restoring */
- StandardFileReply reply; /* User’s choice for PICT file to open */
- SFTypeList typeList; /* Specifies we can open 'PICT' files */
- short pictFileRef; /* File reference number of PICT file */
- OSErr error;
- ExceptionRec exception;
- long msgType;
- long msgCode;
-
- pictDocWindow = nil;
- pictFileRef = 0;
-
- /* Exception-handling section */
- if (ExceptionEntry( /*<*/&exception, /*<*/&msgType, /*<*/&msgCode ))
- {
- if (pictFileRef != 0)
- (void)FSClose( pictFileRef );
- if (pictDocWindow != nil)
- DoClosePictDoc( pictDocWindow );
- (void)ShowAlert( kStopAlert, rOKAlertID, msgType, msgCode );
- return nil;
- }
-
- /* Let the user choose a PICT file */
- typeList [0] = 'PICT';
- if (FileSpecGet( nil, 1, typeList, /*<*/&reply ))
- {
- /* First determine whether chosen file is already open in this app */
- pictDocWindow = FindPictDoc( &reply.sfFile );
- if (pictDocWindow == nil)
- {
- /* Open the PICT file */
- error = HOpenDF( reply.sfFile.vRefNum, reply.sfFile.parID,
- reply.sfFile.name, fsCurPerm, /*<*/&pictFileRef );
- if (error != noErr)
- if (error == opWrErr)
- Exception( &exception, rFileErrMessages,
- kFileErrDocOpenMsg );
- else
- Exception( &exception, rMiscErrMessages,
- kMiscErrUnknownMsg );
-
- /* Get interesting information about a picture */
- error = GetPictureInfo( pictFileRef, /*<*/&pictureInfo );
- if (error != noErr)
- Exception( &exception, rMiscErrMessages, kMiscErrUnknownMsg );
- pictureRect = pictureInfo.frame;
- OffsetRect( /*◊*/&pictureRect, -pictureRect.left,
- -pictureRect.top );
-
- /* Open a new Picture Document window*/
- error = CreatePictDoc( &pictureRect, pictureInfo.depth,
- pictureInfo.colors, /*<*/&pictDocWindow );
- if (error == memFullErr)
- Exception( &exception, rMemErrMessages, kMemErrOpenDocMsg );
- else if (error == resNotFound)
- Exception( &exception, rResErrMessages, kResErrAppDamageMsg );
- else if (error != noErr)
- Exception( &exception, rMiscErrMessages, kMiscErrUnknownMsg );
-
- /* Fill in the Picture Document information */
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( pictDocWindow );
- color.red = color.green = color.blue = 0x0000;
- (**pictDocInfo).foreground = color;
- color.red = color.green = color.blue = 0xFFFF;
- (**pictDocInfo).background = color;
- (**pictDocInfo).fileRef = pictFileRef;
- (**pictDocInfo).file = reply.sfFile;
- (**pictDocInfo).dithering = false;
-
- /* Get a handle to the Picture Document information record */
- pictDocInfo = (PictDocInfoHnd)GetWRefCon( pictDocWindow );
-
- /* Save current port and set newImage as current port */
- newImage = (**pictDocInfo).image;
- GetGWorld( /*<*/&savedPort, /*<*/&savedDevice );
- SetGWorld( newImage, nil );
-
- /* Draw the contents of the PICT file into the current port */
- error = DrawFilePicture( pictFileRef, &newImage->portRect );
-
- /* Restore the current port and check for errors */
- SetGWorld( savedPort, savedDevice );
- if (error != noErr)
- Exception( &exception, rMiscErrMessages, kMiscErrUnknownMsg );
-
- /* Set the title of the window to the title of the file */
- SetWTitle( pictDocWindow, reply.sfFile.name );
-
- /* Show the window in its final size and position */
- ShowWindow( pictDocWindow );
- }
- else
- /* Chosen file already open; just select it */
- SelectWindow( pictDocWindow );
- }
-
- return pictDocWindow;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * CreatePictDoc: Create an empty Picture Document
- *
- * PARAMETERS:
- * Rect *pictureRect: Bounding rectangle of the image
- * WindowPtr *retDoc: Returns pointer to new Picture Document window
- *
- * DEFINITION:
- * This routine creates a new Picture Document window and returns a pointer to
- * it. If the Picture Document couldn’t be created for some reason, then
- * CreatePictDoc returns the error code, and the retDoc parameter is untouched.
- *
- * DESCRIPTION:
- * Space for the window record is allocated before GetNewWindow is called so that]
- * heap fragmentation is minimized. Then, the window is initialized with
- * GetNewWindow. Then the vertical and horizontal scroll bars are created, and
- * the Picture Document information record is allocated and initialized. The
- * last major task is to stagger the window into position, and the routines that
- * are defined in WindowPositioner.c are used to do this.
- *
- * RETURN VALUES:
- * Result: Error code if Picture Document window couldn’t be created
- * retDoc: Pointer to the new Picture Document window,
- \******************************************************************************/
-
- static OSErr CreatePictDoc(
- Rect *pictureRect, /* Bounding rectangle of off-screen image */
- short pictureDepth, /* Pixel depth of off-screen image */
- CTabHandle pictureClut, /* Color table of off-screen image */
- WindowPtr *retDoc) /* Returns ptr to new Picture Document window */
- {
- WindowPtr docWindow; /* Pointer to new Picture Document window */
- Ptr windowStore; /* Pointer to pre-allocated window rec */
- PictDocInfoHnd docInfo; /* Handle to Picture Document information */
- PaletteHandle pictureColors; /* Palette with picture’s colors */
- GWorldPtr newImage; /* New off-screen image */
- ControlHandle vScrollBar; /* Vertical scroll bar */
- ControlHandle hScrollBar; /* Horizontal scroll bar */
- Rect windowRect; /* Destination rectangle of window */
- Point windowBias; /* Bias of Picture Document window */
- OSErr error;
- ExceptionRec exception;
- long msgType;
- long msgCode;
-
- docWindow = nil;
- docInfo = nil;
- windowStore = nil;
-
- /* Exception-handling code */
- if (ExceptionEntry( /*<*/&exception, /*<*/&msgType, /*<*/&msgCode ))
- {
- if (docWindow != nil)
- CloseWindow( docWindow );
- if (windowStore != nil)
- DisposPtr( windowStore );
- if (docInfo != nil)
- DisposHandle( (Handle)docInfo );
- return msgCode;
- }
-
- /* Pre-allocate the window record to avoid heap fragmentation */
- windowStore = NewPtrMargin( sizeof (WindowRecord), kAllocApp, !kAllocClr );
- if (windowStore == nil)
- Exception( &exception, 0, memFullErr );
-
- /* Create the off-screen graphics environment */
- if (pictureClut == nil)
- pictureClut = GetCTable( pictureDepth );
- error = NewGWorld( /*<*/&newImage, pictureDepth, pictureRect, pictureClut,
- nil, 0 );
- if (error != noErr)
- Exception( &exception, 0, error );
-
- /* Create a new Picture Document window */
- docWindow = GetNewCWindow( rPictDocWindID, windowStore,
- (WindowPtr)-1L );
- if (docWindow == nil)
- if (FailLowMemory( 0 ) || ResError() == memFullErr)
- Exception( &exception, 0, memFullErr );
- else if (ResError() == noErr || ResError() == resNotFound)
- Exception( &exception, 0, resNotFound );
- SetPort( docWindow );
-
- /* Give the window a palette with the window colors */
- pictureColors = NewPalette( (**pictureClut).ctSize + 1, pictureClut,
- pmTolerant, 0 );
- SetPalette( docWindow, pictureColors, true );
-
- /* Create the horizontal and vertical scroll bars */
- vScrollBar = GetNewControl( rScrollBarID, docWindow );
- if (vScrollBar == nil)
- if (FailLowMemory( 0 ) || ResError() == memFullErr)
- Exception( &exception, 0, memFullErr );
- else if (ResError() == noErr || ResError() == resNotFound)
- Exception( &exception, 0, resNotFound );
- hScrollBar = GetNewControl( rScrollBarID, docWindow );
- if (hScrollBar == nil)
- if (FailLowMemory( 0 ) || ResError() == memFullErr)
- Exception( &exception, 0, memFullErr );
- else if (ResError() == noErr || ResError() == resNotFound)
- Exception( &exception, 0, resNotFound );
-
- /* Allocate a new Picture Document information record */
- docInfo = (PictDocInfoHnd)NewHandleMargin( sizeof (PictDocInfoRec),
- kAllocApp, !kAllocClr );
- if (docInfo == nil)
- Exception( &exception, rMemErrMessages, kMemErrOpenDocMsg );
- (**docInfo).image = newImage;
- (**docInfo).vScrollBar = vScrollBar;
- (**docInfo).hScrollBar = hScrollBar;
- (**docInfo).destRect = newImage->portRect;
- (**docInfo).fileRef = 0;
- SetWRefCon( docWindow, (long)docInfo );
-
- /* Stagger the window onto the screen */
- windowBias = CalcWindowBias( documentProc,
- ((WindowPeek)docWindow)->goAwayFlag );
- SetRect( /*<*/&windowRect, 0, 0, pictureRect->right + kScrollBarWidth - 1,
- pictureRect->bottom + kScrollBarWidth - 1 );
- LocalToGlobal( /*◊*/&topLeft( windowRect ) );
- LocalToGlobal( /*◊*/&botRight( windowRect ) );
- PositionScreenRect( /*◊*/&windowRect,
- kParentScreenPos, kStaggerPos, NextPictDocWindow( nil ),
- windowBias.h, windowBias.v );
- MoveWindow( docWindow, windowRect.left, windowRect.top, false );
- SizeWindow( docWindow, windowRect.right - windowRect.left,
- windowRect.bottom - windowRect.top, false );
- ResizePictDoc( docWindow );
-
- /* Identify this window for later */
- ((WindowPeek)docWindow)->windowKind = kDocWKind;
-
- *retDoc = docWindow;
- return noErr;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * DoSaveAsPictDoc: Save a new Picture Document
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * The user is asked for a file name for the new Picture Document file through
- * Standard File. If the user specifies the file name and location and chooses
- * OK, DoSaveAsPictDoc creates a new PICT file if it didn’t exist already, and
- * then it opens the PICT file for writing. The Picture Document’s off-screen
- * GrafPort is set as the current port, and then OpenFilePicture (defined below)
- * is called which opens a new picture for spooling. Then the off-screen image
- * is CopyBits’ed on top of itself which spools the off-screen image to the PICT
- * file. Then the spooled picture is closed, which completes the writing of the
- * PICT file.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- void DoSaveAsPictDoc(
- WindowPtr docWindow) /* Pointer to Picture Document window being saved */
- {
- StandardFileReply reply; /* Location and name of new PICT file */
- Str255 docTitle; /* Holds the existing name of the document */
- PictDocInfoHnd docInfo; /* Handle to Picture Document information */
- CGrafPtr image; /* Points to document’s image */
- CGrafPtr savedPort; /* Saves current port for later restoring */
- GDHandle savedDevice; /* Saves current GDevice for restoring */
- short pictFileRef; /* File reference number of PICT file */
- OSErr error;
- ExceptionRec exception;
- long msgType;
- long msgCode;
-
- pictFileRef = 0;
-
- /* Exception-handling code */
- if (ExceptionEntry( /*<*/&exception, /*<*/&msgType, /*<*/&msgCode ))
- {
- if (pictFileRef != 0)
- (void)FSClose( pictFileRef );
- return;
- }
-
- /* Get the name and location of the new file from the user */
- GetWTitle( docWindow, /*<*/docTitle );
- StandardPutFile( "\P", docTitle, &reply );
- if (reply.sfGood)
- {
- /* Create the new PICT file if it doesn’t already exist */
- if (!reply.sfReplacing)
- {
- error = HCreate( reply.sfFile.vRefNum, reply.sfFile.parID,
- reply.sfFile.name, kFileCreator, kFileType );
- if (error != noErr)
- Exception( &exception, rMiscErrMessages, kMiscErrUnknownMsg );
- }
-
- /* Open the new PICT file */
- error = HOpen( reply.sfFile.vRefNum, reply.sfFile.parID,
- reply.sfFile.name, fsCurPerm, /*<*/&pictFileRef );
- if (error != noErr)
- Exception( &exception, rMiscErrMessages, kMiscErrUnknownMsg );
-
- /* Get the Picture Document’s image and make it the current port */
- docInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
- image = (**docInfo).image;
- GetGWorld( /*<*/&savedPort, /*<*/&savedDevice );
- SetGWorld( image, nil );
-
- /* Create a PICT file with the Picture Document’s image */
- error = OpenFilePicture( pictFileRef, &image->portRect );
- if (error != noErr)
- Exception( &exception, rMiscErrMessages, kMiscErrUnknownMsg );
- CopyBits( &((GrafPtr)image)->portBits, &((GrafPtr)image)->portBits,
- &image->portRect, &image->portRect,
- srcCopy, nil );
- error = CloseFilePicture();
- if (error != noErr)
- Exception( &exception, rMiscErrMessages, kMiscErrUnknownMsg );
-
- /* Restore the current port */
- SetGWorld( savedPort, savedDevice );
-
- /* Close the existing PICT file if any */
- if ((**docInfo).fileRef != 0)
- (void)FSClose( (**docInfo).fileRef );
-
- /* Remember the new PICT file’s reference number */
- (**docInfo).fileRef = pictFileRef;
- (**docInfo).file = reply.sfFile;
-
- /* Set the title of the window to the title of the file */
- SetWTitle( docWindow, reply.sfFile.name );
- }
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * DoClosePictDoc: Close a Picture Document window
- *
- * PARAMETERS:
- * See PictDocument.h
- *
- * DEFINITION:
- * See PictDocument.h
- *
- * DESCRIPTION:
- * The off-screen image is disposed of and the Picture Document’s PICT file is
- * closed. Then all the memory associated with the window is disposed of.
- *
- * RETURN VALUES:
- * See PictDocument.h
- \******************************************************************************/
-
- Boolean DoClosePictDoc(
- WindowPtr docWindow) /* Ptr to Picture Document window being closed */
- {
- PictDocInfoHnd docInfo; /* Handle to Picture Document info record */
-
- docInfo = (PictDocInfoHnd)GetWRefCon( docWindow );
- if (docInfo != nil)
- {
- /* Get rid of the off-screen CGrafPort */
- if ((**docInfo).image != nil)
- DisposeGWorld( (**docInfo).image );
-
- /* Close the Picture File */
- if ((**docInfo).fileRef != 0)
- (void)FSClose( (**docInfo).fileRef );
-
- /* Dispose of the Picture Document information record */
- DisposHandle( (Handle)docInfo );
- }
-
- /* Close and dispose of the Picture Document window */
- DisposePalette( GetPalette( docWindow ) );
- CloseWindow( docWindow );
- DisposPtr( (Ptr)docWindow );
-
- return true;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * GetPictureInfo: Get basic information about a PICT document
- *
- * PARAMETERS:
- * short pictFileRef: File reference number of PICT file
- * PictureInfoRec *retPictRect: Returns information on picture
- *
- * DEFINITION:
- * GetPictureInfo examines the PICT file whose file reference number is specified
- * in the pictFileRef parameter to get the picFrame of the picture, and the pixel
- * depth and color table of the deepest PixMap in the picture. This information
- * is returned in the retPictInfo parameter.
- *
- * DESCRIPTION:
- * GetPictureInfo uses picture spooling to get the information about the picture
- * in the specified PICT file. A temporary CGrafPort or GrafPort is set up just
- * so that no existing ports are touched. Then a CQDProcs or QDProcs record is
- * set up so that picture data comes from the PICT file instead of memory, and so
- * that any CopyBits calls within the picture get routed to the InfoBits routine
- * (defined below). Then the standard picture spooling mechanism is used to read
- * the PICT file. The clip region is set to nothing to prevent drawing——only the
- * information about the PixMaps is needed, and InfoBits gets that.
- *
- * RETURN VALUES:
- * Result: Error code if anything went wrong
- * retPictInfo: Size of picture, and depth and color table of deepest PixMap in
- * the picture.
- \******************************************************************************/
-
- static OSErr GetPictureInfo(
- short pictFileRef, /* File reference number of PICT file */
- PictureInfoRec *retPictInfo) /* Returns information on picture */
- {
- CGrafPort tempPort; /* Temp port used for “Drawing” pict */
- Boolean tempPortOpen; /* True if tempPort has been opened */
- GrafPtr savedPort; /* Saves current port for restoring */
- CQDProcs customProcs; /* Custom GrafProcs */
- PicHandle spoolPict; /* Picture used for spooling */
- Rect emptyRect; /* Used to set empty clipping region */
- long dataLen; /* Number of bytes of data to read */
- long qdVersion; /* Version number of QuickDraw */
- OSErr error;
- ExceptionRec exception;
- long errorCode;
-
- error = noErr;
- tempPortOpen = false;
- savedPort = nil;
- spoolPict = nil;
-
- /* Exception-handling code */
- if (ExceptionEntry( /*<*/&exception, nil, /*<*/&errorCode ))
- {
- SetPort( savedPort );
- if (tempPortOpen)
- ClosePort( (GrafPtr)&tempPort );
- if (spoolPict != nil)
- DisposHandle( (Handle)spoolPict );
- return errorCode;
- }
-
- /* Get the current version of QuickDraw */
- (void)Gestalt( gestaltQuickdrawVersion, /*<*/&qdVersion );
-
- /* Save current port so that we can restore it later */
- GetPort( /*<*/&savedPort );
-
- /* Open the temporary CGrafPort or GrafPort, depending on QD version */
- if (qdVersion >= gestalt8BitQD)
- OpenCPort( &tempPort );
- else
- OpenPort( (GrafPtr)&tempPort );
- tempPortOpen = true;
-
- /* Don’t want anything drawn */
- SetRect( /*<*/&emptyRect, 0, 0, 0, 0 );
- ClipRect( &emptyRect );
-
- /* Set up the GrafProcs for spooling */
- if (qdVersion >= gestalt8BitQD)
- SetStdCProcs( /*<*/&customProcs );
- else
- SetStdProcs( /*<*/(QDProcsPtr) &customProcs );
- customProcs.bitsProc = (Ptr)InfoBits;
- customProcs.getPicProc = (Ptr)FileGetPic;
-
- /* Install the custom GrafProcs into the tempPort */
- tempPort.grafProcs = &customProcs;
-
- /* Create the picture used for spooling */
- spoolPict = (PicHandle)NewHandleMargin( sizeof (Picture), kAllocApp,
- !kAllocClr );
- if (spoolPict == nil)
- Exception( &exception, 0, memFullErr );
-
- /* Skip the PICT file header */
- error = SetFPos( pictFileRef, fsFromStart, 512L );
- if (error != noErr)
- Exception( &exception, 0, error );
-
- /* Read the picture header into spoolPict */
- dataLen = sizeof (Picture);
- error = FSRead( pictFileRef, /*◊*/&dataLen, (Ptr) *spoolPict );
- if (error != noErr)
- Exception( &exception, 0, error );
-
- /* Spool the picture in */
- gPictureInfo.colors = nil;
- gPictureInfo.depth = 0;
- gPictureInfo.frame = (**spoolPict).picFrame;
- gPictFileRef = pictFileRef;
- DrawPicture( spoolPict, &gPictureInfo.frame );
-
- /* Clean up after myself */
- SetPort( savedPort );
- ClosePort( (GrafPtr)&tempPort );
- tempPortOpen = false;
- DisposHandle( (Handle)spoolPict );
-
- /* Return picture information */
- *retPictInfo = gPictureInfo;
- return noErr;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * InfoBits: GrafProc to get information about bit/pixel maps
- *
- * PARAMETERS:
- * BitMapPtr srcBits: Pointer to bit/pixel map being transferred
- * Rect *srcRect: Source rectangle of CopyBits call; ignored
- * Rect *dstRect: Destination rectangle of CopyBits call; ignored
- * short mode: Transfer mode; ignored
- * RgnHandle maskRgn: Region to mask CopyBits; ignored
- *
- * DEFINITION:
- * InfoBits is a custom QuickDraw graphics procedure which is used to find the
- * depth and color table of the deepest PixMap in the picture that’s being drawn.
- * This information is returned in the gPictureInfo global variable.
- *
- * DESCRIPTION:
- * InfoBits is called every time a CopyBits call is found in a picture that’s
- * being drawn. It first checks to see if the CopyBits call is for a PixMap or
- * a BitMap. If it’s a BitMap, the most significant bit of rowBytes is clear; if
- * it’s a PixMap, the most significant byte of rowBytes is set. If it’s a
- * PixMap, its depth is compared against the depth of any previous PixMap that
- * has been seen in the picture. If it’s deeper, then the depth and color table
- * of the PixMap is saved. Otherwise, the PixMap is ignored.
- *
- * If srcBits is a BitMap and no PixMaps have yet been seen in the picture, then
- * InfoBits remembers a depth of 1 bit per pixel and no color table.
- *
- * RETURN VALUES:
- * gPictureInfo: Depth and color table of deepest PixMap in a picture.
- \******************************************************************************/
-
- static pascal void InfoBits(
- BitMapPtr srcBits, /* Pointer to bit/pixel map being transferred */
- Rect *srcRect, /* Source rectangle of CopyBits call; ignored */
- Rect *dstRect, /* Destination rectangle of CopyBits call; ignored */
- short mode, /* Transfer mode; ignored */
- RgnHandle maskRgn) /* Region to mask CopyBits; ignored */
- {
- #pragma unused (srcRect,dstRect,mode,maskRgn)
- PixMapPtr srcPix; /* Handle to the picture’s PixMap */
-
- if (srcBits->rowBytes & 0x8000)
- {
- /* srcBits is a pixel map, get depth and color table */
- srcPix = (PixMapPtr)srcBits;
-
- /* Only save info if this pixel map is deepest seen so far */
- if (srcPix->pixelSize > gPictureInfo.depth)
- {
- gPictureInfo.depth = srcPix->pixelSize;
- if (srcPix->pixelType != RGBDirect)
- {
- if (gPictureInfo.colors != nil)
- DisposHandle( (Handle)gPictureInfo.colors );
- gPictureInfo.colors = srcPix->pmTable;
- HandToHand( (Handle *)&gPictureInfo.colors );
- }
- }
- }
- else
- {
- /* srcBits is a bit map, has depth of 1 and B&W color table */
- if (gPictureInfo.depth == 0)
- {
- gPictureInfo.depth = 1;
- if (gPictureInfo.colors != nil)
- DisposHandle( (Handle)gPictureInfo.colors );
- gPictureInfo.colors = nil;
- }
- }
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * DrawFilePicture: Read a PICT file into the current GrafPort
- *
- * PARAMETERS:
- * short pictFileRef: File reference number of PICT file to open
- * Rect *destRect: Rectangle to draw the picture into
- *
- * DEFINITION:
- * This routine is used to read the picture data from the PICT file specified by
- * pictFileRef and draw the picture into the rectangle specified by the destRect
- * parameter in the current GrafPort. It’s just like DrawPicture, except the
- * file reference number of a PICT file is specified instead of a PicHandle.
- *
- * DESCRIPTION:
- * DrawFilePicture works by using the picture spooling method described in Inside
- * Macintosh V on pages 87 through 90. In this method, the getPicProc GrafProc is
- * replaced by my routine called FileGetPic which reads PICT information from
- * disk. By doing this, the DrawPicture command effectively reads PICT files.
- *
- * After setting up the GrafProcs record, this routine installs the GrafProcs
- * into the current port. Then, a temporary picture is manually allocated and
- * placed into spoolPict. This is essentially a placeholder to hold the picture
- * header (which is different from the 512-byte PICT file header) and is always
- * the size of the Picture record type without any picture data.
- *
- * The PICT file is opened using HOpen. HOpen is documented in the File Manager
- * chapter of Inside Macintosh VI, but it still works on pre-7.0 machines because
- * it’s just glue code that calls PBHOpen. Because of the way the File Manager
- * works, this routine also works on MFS volumes. This routine is preferable to
- * FSOpen because HOpen allows you to specify access permissions, and because it
- * lets you specify a file by the more reliable volume reference number,
- * directory ID, and file name rather than by working directory reference number
- * and file name. I’m using the FSSpec record to hold file information, so
- * specifying a file like this is especially convenient. If this were a 7.0-only
- * application, I’d call FSpOpen instead of HOpen because FSpOpen takes an FSSpec
- * record directly.
- *
- * After the PICT file is opened, SetFPos is called to skip the first 512 bytes
- * of the file. The first 512 bytes of a PICT file is called the PICT file
- * header (not to be confused with the picture header, which contains the picSize
- * and picFrame fields of the Picture type) and holds application-specific
- * information. This application doesn’t care what’s there so it just skips it.
- * The picture header follows the PICT file header and is read into spoolPict.
- *
- * Finally (almost), DrawPicture is called. Because this routine replaced the
- * current port’s GrafProcs with my own, DrawPicture gets the picture information
- * from the PICT file rather than from spoolPict. It draws the picture into the
- * current port.
- *
- * RETURN VALUES:
- * Result: Returns an error code.
- * destRect: Returns the picFrame of the picture in the PICT file
- \******************************************************************************/
-
- static OSErr DrawFilePicture(
- short pictFileRef, /* File reference number of PICT file to open */
- Rect *destRect) /* Rectangle to draw the picture into */
- {
- GrafPtr currPort; /* Ptr to current port used for Drawing pict */
- CQDProcs customProcs; /* Custom GrafProcs */
- QDProcsPtr savedProcs; /* Current GrafPort’s QD procs; used to restore */
- PicHandle spoolPict; /* Picture used for spooling */
- long dataLen; /* Number of bytes of data to read */
- long qdVersion; /* Version number of QuickDraw */
- OSErr error;
- ExceptionRec exception;
- long errorCode;
-
- currPort = nil;
- spoolPict = nil;
- savedProcs = nil;
- error = noErr;
-
- /* Exception-handling code */
- if (ExceptionEntry( /*<*/&exception, nil, /*<*/&errorCode ))
- {
- if (spoolPict != nil)
- DisposHandle( (Handle)spoolPict );
- if (savedProcs != nil)
- currPort->grafProcs = savedProcs;
- return errorCode;
- }
-
- /* Get the current version of QuickDraw */
- (void)Gestalt( gestaltQuickdrawVersion, /*<*/&qdVersion );
-
- /* Get a pointer to the current port and determine its type */
- GetPort( /*<*/&currPort );
-
- /* Initialize the GrafProcs for reading from a PICT file */
- if (qdVersion >= gestalt8BitQD)
- SetStdCProcs( /*<*/&customProcs );
- else
- SetStdProcs( /*<*/(QDProcsPtr) &customProcs );
- customProcs.getPicProc = (Ptr)FileGetPic;
-
- /* Install the custom GrafProcs into the tempPort */
- savedProcs = currPort->grafProcs;
- currPort->grafProcs = (QDProcsPtr)&customProcs;
-
- /* Create the temporary picture used for spooling */
- spoolPict = (PicHandle)NewHandleMargin( sizeof (Picture),
- kAllocApp, !kAllocClr );
- if (spoolPict == nil)
- Exception( &exception, 0, memFullErr );
-
- /* Skip the 512-byte PICT file header */
- error = SetFPos( pictFileRef, fsFromStart, kPictFileHeaderSize );
- if (error != noErr)
- Exception( &exception, 0, error );
-
- /* Read the picture header (not PICT file header) into spoolPict */
- dataLen = sizeof (Picture);
- error = FSRead( pictFileRef, /*◊*/&dataLen, (Ptr)*spoolPict );
- if (error != noErr)
- Exception( &exception, 0, error );
-
- /* Spool the picture in */
- gPictFileRef = pictFileRef;
- DrawPicture( spoolPict, destRect );
-
- /* Clean up after myself */
- DisposHandle( (Handle)spoolPict );
- currPort->grafProcs = savedProcs;
-
- return noErr;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * FileGetPic: Get QuickDraw picture information from a file
- *
- * PARAMETERS:
- * Ptr dataPtr: Points to location that picture data should be placed
- * short byteCount: Number of bytes of picture data to read
- *
- * DEFINITION:
- * This routine is a custom QuickDraw graphics procedure which replaces the
- * standard GetPicProc. QuickDraw graphics procedures are routines that
- * QuickDraw calls to do almost everything that it does, like drawing rectangles,
- * or getting picture data. They can be replaced by setting up a QDProcs record
- * and setting the appropriate field to point to the custom QuickDraw graphics
- * procedure. In this case, the getPicProc field is set to point to FileGetPic
- * so that any DrawPicture call within the GrafPort causes FileGetPic to be
- * called to get picture data. Instead of getting picture data from memory,
- * FileGetPic gets picture data from the disk file whose file reference number is
- * stored in the gPictFileRef global variable.
- *
- * DESCRIPTION:
- * FileGetPic simply calls FSRead to read data from the file whose file reference
- * number is stored in gPictFileRef into the area pointed to by dataPtr, which is
- * an area of memory that’s set up by QuickDraw to receive picture data. The
- * number of bytes of picture data that QuickDraw wants is specified by the
- * byteCount parameter.
- *
- * RETURN VALUES:
- * None
- \******************************************************************************/
-
- static pascal void FileGetPic(
- Ptr dataPtr, /* Points to location that picture data should be placed */
- short byteCount) /* Number of bytes of picture data to read */
- {
- long longCount; /* Number of bytes to read from the PICT file */
-
- longCount = byteCount;
- (void)FSRead( gPictFileRef, /*◊*/&longCount, dataPtr );
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * OpenFilePicture: Open a picture for spooling to a file
- *
- * PARAMETERS:
- * short pictFileRef: File reference number of PICT file to write to
- * Rect *sourceRect: Rectangle to draw the picture from
- *
- * DEFINITION:
- * Normally, when you create a picture, you call OpenPicture, draw, then call
- * ClosePicture. But if you can create a PICT file in a similar way by calling
- * OpenFilePicture and CloseFilePicture. Almost like you would normally, you
- * should set up the current port however you want it, call OpenFilePicture,
- * use QuickDraw routines to draw, then call CloseFilePicture when you’re done.
- * But before you call OpenFilePicture, you must open the PICT file for writing,
- * and pass the file’s reference number in the pictFileRef parameter. Once
- * CloseFilePicture is called, the PICT file is complete.
- *
- * DESCRIPTION:
- * OpenFilePicture installs the FilePutPic custom graphics procedure by setting
- * up a QDprocs record with the default pointers, and then setting the putPicProc
- * field to point to the FilePutPic function. This QDProcs record is then
- * installed into the current GrafPort. Then, an empty picture is allocated just
- * to have something to pass to the real OpenPicture routine. Then the 512-byte
- * PICT file header is written. This program doesn’t do anything with those 512
- * bytes, so only zeroes are written. Also, the ten-byte picture header is
- * written with zeroes for now; it’ll get the real picture header after the PICT
- * file data is written. Finally, the global variables are set up so that
- * FilePutPic can reach them.
- *
- * RETURN VALUES:
- * Result: Error code of any error that occurs.
- \******************************************************************************/
-
- static OSErr OpenFilePicture(
- short pictFileRef, /* File reference number of PICT file to open */
- Rect *sourceRect) /* Rectangle to draw the picture from */
- {
- GrafPtr currPort; /* Ptr to current port used for Drawing pict */
- long dataLen; /* Number of bytes of data to write */
- short zeroData; /* Equal to 0; used to write PICT file header */
- short count; /* Generic counter */
- OSErr error;
- ExceptionRec exception;
- long errorCode;
-
- currPort = nil;
- gSpoolPicture = nil;
- gSavedProcs = nil;
- error = noErr;
-
- /* Exception-handling code */
- if (ExceptionEntry( /*<*/&exception, nil, /*<*/&errorCode ))
- {
- if (gSpoolPicture != nil)
- DisposHandle( (Handle)gSpoolPicture );
- if (gSavedProcs != nil)
- currPort->grafProcs = gSavedProcs;
- return errorCode;
- }
-
- /* Get a pointer to the current port */
- GetPort( /*<*/&currPort );
-
- /* Initialize the GrafProcs for reading from a PICT file */
- if (currPort->portBits.rowBytes & 0x8000)
- SetStdCProcs( /*<*/&gCustomProcs );
- else
- SetStdProcs( /*<*/(QDProcsPtr)&gCustomProcs );
- gCustomProcs.putPicProc = (Ptr)FilePutPic;
-
- /* Install the custom GrafProcs into the tempPort */
- gSavedProcs = currPort->grafProcs;
- currPort->grafProcs = (QDProcsPtr)&gCustomProcs;
-
- /* Create the temporary picture used for spooling */
- gSpoolPicture = (PicHandle)NewHandleMargin( sizeof (Picture),
- kAllocApp, kAllocClr );
- if (gSpoolPicture == nil)
- Exception( &exception, 0, memFullErr );
-
- /* Make sure we’re positioned at the beginning of the file */
- error = SetFPos( pictFileRef, fsFromStart, 0 );
- if (error != noErr)
- Exception( &exception, 0, error );
-
- /* Zero the 512-byte PICT file header */
- dataLen = sizeof (short);
- zeroData = 0;
- for (count = 0; count < (kPictFileHeaderSize + sizeof (Picture))
- / sizeof (short); ++count)
- {
- error = FSWrite( pictFileRef, /*◊*/&dataLen, &zeroData );
- if (error != noErr)
- Exception( &exception, 0, error );
- }
-
- /* Begin spooling the picture out */
- gPictFileRef = pictFileRef;
- gPictureSize = sizeof (Picture);
- gSpoolPicture = nil;
- gSpoolPicture = OpenPicture( sourceRect );
-
- return noErr;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * CloseFilePicture: Close a spooled picture (don’t close the PICT file)
- *
- * PARAMETERS:
- * None
- *
- * DEFINITION:
- * ClosePictureFile is called to complete the writing of a PICT file. It’s
- * called the same way you’d call ClosePicture.
- *
- * DESCRIPTION:
- * ClosePicture is called to close the currently-open picture, then the picture
- * header is written with the final values. Because the temporary picture isn’t
- * needed anymore, KillPicture is called to get rid of it. Finally, the current
- * port’s graphics procedures are restored to what they were before
- * OpenFilePicture was called.
- *
- * RETURN VALUES:
- * Result: Error code of any error that occurs.
- \******************************************************************************/
-
- static OSErr CloseFilePicture()
- {
- long dataLen; /* Number of bytes of data to write */
- GrafPtr currPort; /* Pointer to the current GrafPort */
- OSErr error;
- ExceptionRec exception;
- long errorCode;
-
- error = noErr;
-
- /* Exception-handling code */
- if (ExceptionEntry( /*<*/&exception, nil, /*<*/&errorCode ))
- {
- return errorCode;
- }
-
- /* Close the spooled picture */
- ClosePicture();
-
- /* Make sure we’re positioned just past the PICT file header */
- error = SetFPos( gPictFileRef, fsFromStart, kPictFileHeaderSize );
- if (error != noErr)
- Exception( &exception, 0, error );
-
- /* Write the picture header (NOT the PICT file header!) */
- dataLen = sizeof (Picture);
- error = FSWrite( gPictFileRef, /*◊*/&dataLen, (Ptr)*gSpoolPicture );
- if (error != noErr)
- Exception( &exception, 0, error );
-
- /* Dispose of the picture */
- KillPicture( gSpoolPicture );
-
- /* Restore the previous graphics procedures */
- GetPort( /*<*/&currPort);
- currPort->grafProcs = gSavedProcs;
- }
-
-
- /******************************************************************************\
- * NAME & SYNOPSIS:
- * FilePutPic: Write QuickDraw picture information to PICT file
- *
- * PARAMETERS:
- * Ptr dataPtr: Points to location of picture data
- * short byteCount: Number of bytes of picture data to write
- *
- * DEFINITION:
- * This routine is a custom QuickDraw graphics procedure which replaces the
- * standard PutPicProc. QuickDraw graphics procedures are routines that
- * QuickDraw calls to do almost everything that it does, like drawing rectangles,
- * or getting picture data. They can be replaced by setting up a QDProcs record
- * and setting the appropriate field to point to the custom QuickDraw graphics
- * procedure. In this case, the getPicProc field is set to point to FileGetPic
- * so that any drawing call within the GrafPort while a picture is open causes
- * FilePutPic to be called to write picture data. Instead of writing picture
- * data to memory, FileGetPic writes picture data to the disk file whose file
- * reference number is stored in the gPictFileRef global variable.
- *
- * DESCRIPTION:
- * FileGetPic calls FSWrite to write data t=o the file whose file reference
- * number is stored in gPictFileRef from the area pointed to by dataPtr, which is
- * an area of memory that’s set up by QuickDraw to hold picture data. The
- * number of bytes of picture data that QuickDraw has is specified by the
- * byteCount parameter. Also, the picSize field of gSpoolPicture is updated so
- * that QuickDraw can keep track of the current size of the picture.
- *
- * RETURN VALUES:
- * None
- \******************************************************************************/
-
- static pascal void FilePutPic(
- Ptr dataPtr, /* Points to location of picture data */
- short byteCount) /* Number of bytes of picture data to write */
- {
- long dataLen; /* Number of bytes to write the PICT file */
-
- dataLen = byteCount;
- gPictureSize += dataLen;
- (void)FSWrite( gPictFileRef, /*◊*/&dataLen, dataPtr );
- if (gSpoolPicture != nil)
- (**gSpoolPicture).picSize = gPictureSize;
- }
-